﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.Xml.Linq;

namespace GameTank
{
    public class CharacterDTO
    {
        public CharacterDTO()
        {
            defaulCreate();
        }

        public CharacterDTO(CharacterDTO orther)
        {
            if (orther == null)
            {
                defaulCreate();
            }
            else
            {
                this._acttack = orther._acttack;
                this._currentExp = orther._currentExp;
                this._currentHp = orther._currentHp;
                this._currentMana = orther.CurrentMana;
                this._defense = orther._defense;
                this._direction = orther._direction;
                this._exp = orther._exp;
                this._faction = orther._faction;
                this._hp = orther._hp;
                this._level = orther._level;
                this._mana = orther._mana;
                this.MoveSpeed = orther.MoveSpeed;
                this.Direction = orther.Direction;
                this._pos = orther._pos;
                this._currentFrame = orther._currentFrame;
                this._timeDelay = orther._timeDelay;
                this.Weapons = orther._listWeaponDTOs;
            }
        }

        private void defaulCreate()
        {
            this._acttack = 20;
            this._hp = 100;
            this._currentHp = 100;
            this._mana = 50;
            this._pos = Vector2.Zero;
            this._exp = 100;
            this._moveSpeed = 3.0f;
            this._currentFrame = 0;
            this._timeDelay = 50.0f;
            this.Living = true;
            this._listWeaponDTOs = new List<WeaponDTO>();
            this._level = 1;

            this._duration = TimeSpan.Zero;

            for (int i = 0; i < 5; ++i)
            {
                Weapons.Add(new WeaponDTO());
            }
        }

        string livingModel = "Ourtank.mdd";

        public string LivingModel
        {
            get { return livingModel; }
            set { livingModel = value; }
        }
        string explodingModel = "explodingTank.mdd";

        public string ExplodingModel
        {
            get { return explodingModel; }
            set { explodingModel = value; }
        }

        string controller = "AIController";

        public string Controller
        {
            get { return controller; }
            set { controller = value; }
        }

        protected string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private int _level;

        public int Level
        {
            get { return _level; }
            set { _level = value; }
        }

        private int _exp;

        public int Exp
        {
            get { return _exp; }
            set { _exp = value; }
        }

        int _currentExp;

        public int CurrentExp
        {
            get { return _currentExp; }
            set { _currentExp = value; }
        }

        private float _hp;

        public float Hp
        {
            get { return _hp; }
            set { _hp = value; }
        }

        float _currentHp;

        public float CurrentHp
        {
            get { return _currentHp; }
            set { _currentHp = value; }
        }

        private float _mana;

        public float Mana
        {
            get { return _mana; }
            set { _mana = value; }
        }

        float _currentMana;

        public float CurrentMana
        {
            get { return _currentMana; }
            set { _currentMana = value; }
        }

        private float _acttack;

        public float Acttack
        {
            get { return _acttack; }
            set { _acttack = value; }
        }

        private float _defense;

        public float Defense
        {
            get { return _defense; }
            set { _defense = value; }
        }

        private Vector2 _velocity;

        public Vector2 Velocity
        {
            get { return _velocity * _moveSpeed; }
        }


        float _moveSpeed;

        public float MoveSpeed
        {
            get { return _moveSpeed; }
            set { _moveSpeed = value; }

        }

        private Vector2 _pos;

        public Vector2 Pos
        {
            get { return _pos; }
            set { _pos = value; }
        }

        int _direction;

        public int Direction
        {
            get { return _direction; }
            set
            {
                {
                    if ((value <= 1 && _direction > 1) || (value > 1 && _direction <= 1))
                    {
                        _pos.X += (_width - _height) / 2;
                        _pos.Y += (_height - _width) / 2;
                    }
                }
                _direction = value;
                _velocity *= 0;
                switch (_direction)
                {
                    case 0:
                        _velocity.Y = -1;
                        break;
                    case 1:
                        _velocity.Y = 1;
                        break;
                    case 2:
                        _velocity.X = -1;
                        break;

                    case 3:
                        _velocity.X = 1;
                        break;
                }
            }
        }

        private int _faction;

        public int Faction
        {
            get { return _faction; }
            set { _faction = value; }
        }

        int _height;

        public int Height
        {
            get { return _height; }
            set { _height = value; }
        }
        int _width;

        public int Width
        {
            get { return _width; }
            set { _width = value; }
        }

        int _currentFrame;

        public int CurrentFrame
        {
            get { return _currentFrame; }
            set { _currentFrame = value; }
        }

        float _timeDelay;

        public float TimeDelay
        {
            get { return _timeDelay; }
            set { _timeDelay = value; }
        }



        public int nWeapons
        {
            get { return _listWeaponDTOs.Count; }
            set { }
        }
        List<WeaponDTO> _listWeaponDTOs;

        public List<WeaponDTO> Weapons
        {
            get { return _listWeaponDTOs; }
            set { _listWeaponDTOs = value; }
        }

        int _layer;

        public int Layer
        {
            get { return _layer; }
            set { _layer = value; }
        }

        bool _ready;

        public bool Ready
        {
            get { return _ready; }
            set
            {
                if (value)
                {
                    _living = false;
                    _exploding = false;
                }
                _ready = value;
            }
        }
        bool _living;

        public bool Living
        {
            get { return _living; }
            set
            {
                if (value)
                {
                    _ready = false;
                    _exploding = false;
                }
                _living = value;
            }
        }

        bool _exploding;

        public bool Exploding
        {
            get { return _exploding; }
            set
            {
                if (value)
                {
                    _living = false;
                    _ready = false;
                }
                _exploding = value;
            }
        }

        TimeSpan _duration;

        public TimeSpan Duration
        {
            get { return _duration; }
            set { _duration = value; }
        }
        float _acttackSpeed;

        public float ActtackSpeed
        {
            get { return _acttackSpeed; }
            set { _acttackSpeed = value; }
        }

        public XElement ToXml()
        {
            XElement element = new XElement("Character");

            element.SetAttributeValue("livingModel", this.livingModel);

            element.SetAttributeValue("explodingModel", this.explodingModel);

            element.SetAttributeValue("controller", this.controller);

            element.SetAttributeValue("name", Name);

            element.SetAttributeValue("level", this.Level);
            
            element.SetAttributeValue("exp", this.Exp);
            
            element.SetAttributeValue("currentexp", this.CurrentExp);

            element.SetAttributeValue("hp", this.Hp);

            element.SetAttributeValue("currenthp", this.CurrentHp);

            element.SetAttributeValue("mana", this.Mana);

            element.SetAttributeValue("currentmana", this.CurrentMana);

            element.SetAttributeValue("attack", this.Acttack);

            element.SetAttributeValue("defense", this.Defense);

            element.SetAttributeValue("movespeed", this.MoveSpeed);

            element.Add(new XElement("pos",new XAttribute("x", this.Pos.X),new XAttribute("y",this.Pos.Y)));

            element.SetAttributeValue("direction", this.Direction);

            element.SetAttributeValue("faction", this.Faction);

            element.SetAttributeValue("height", this.Height);

            element.SetAttributeValue("width", this.Width);

            element.SetAttributeValue("currentframe", this.CurrentFrame);

            element.SetAttributeValue("timedelay", this.TimeDelay);

            element.SetAttributeValue("layer", this.Layer);

            element.SetAttributeValue("ready", this.Ready);

            element.SetAttributeValue("living", this.Living);

            element.SetAttributeValue("exploding", this.Exploding);

            element.SetAttributeValue("duration", this.Duration.ToString());

            element.SetAttributeValue("attackspeed", this.ActtackSpeed);

            element.Add(ToXml(this.Weapons));
            return element;
        }

        public XElement ToXml(List<WeaponDTO> listWeapons)
        {

            XElement element = new XElement("listWeapons");
            element.SetAttributeValue("value", Weapons.Count);
            for (int i = 0; i < Weapons.Count; ++i)
            {
                element.Add(Weapons[i].ToXml());
            }
            return element;
        }

        public static CharacterDTO Parse(XElement element)
        {
            CharacterDTO character = new CharacterDTO();

            character.LivingModel = element.Attribute("livingModel").Value;

            character.ExplodingModel = element.Attribute("explodingModel").Value;

            character.controller = element.Attribute("controller").Value;

            character.Name = element.Attribute("name").Value;

            character.Level = int.Parse(element.Attribute("level").Value);

            character.Exp = int.Parse(element.Attribute("exp").Value);

            character.CurrentExp = int.Parse(element.Attribute("currentexp").Value);

            character.Hp = int.Parse(element.Attribute("hp").Value);

            character.CurrentHp = float.Parse(element.Attribute("currenthp").Value);

            character.Mana = float.Parse(element.Attribute("mana").Value);

            character.CurrentMana = float.Parse(element.Attribute("currentmana").Value);

            character.Acttack = float.Parse(element.Attribute("attack").Value);

            character.Defense = float.Parse(element.Attribute("defense").Value);

            character.MoveSpeed = float.Parse(element.Attribute("movespeed").Value);

            int x = int.Parse(element.Element("pos").Attribute("x").Value);
            int y = int.Parse(element.Element("pos").Attribute("y").Value);
            character.Pos = new Vector2(x, y);

            character.Direction = int.Parse(element.Attribute("direction").Value);

            character.Faction = int.Parse(element.Attribute("faction").Value);

            character.Height = int.Parse(element.Attribute("height").Value);

            character.Width = int.Parse(element.Attribute("level").Value);

            character.CurrentFrame = int.Parse(element.Attribute("currentframe").Value);

            character.TimeDelay = float.Parse(element.Attribute("timedelay").Value);

            character.Layer = int.Parse(element.Attribute("layer").Value);

            character.Ready = bool.Parse(element.Attribute("ready").Value);

            character.Living = bool.Parse(element.Attribute("living").Value);

            character.Exploding = bool.Parse(element.Attribute("exploding").Value);

            character.Duration = TimeSpan.Parse(element.Attribute("duration").Value);

            character.ActtackSpeed = float.Parse(element.Attribute("attackspeed").Value);

            character.Weapons   = ReadistWeapons(element.Element("listWeapons"));
            return character;
        }

        public static List<WeaponDTO> ReadistWeapons(XElement element)
        {
            List<WeaponDTO> kq = new List<WeaponDTO>();
            var Elements = element.Descendants("Weapon");
            foreach (var XEle in Elements)
            {
                kq.Add(WeaponDTO.Parse(XEle));
            }
            return kq;
        }

        public void SaveToFile(String fileName)
        {
            XDocument doc = new XDocument();
            doc.Add(ToXml());
            doc.Save(fileName);
        }
       
    }// end class CharectorDTO;
}
